package com.hly.tool.file;


import com.hly.tool.constants.Constants;
import com.hly.tool.object.HDomainObject;
import com.matrixone.apps.common.Document;
import com.matrixone.apps.common.Task;
import com.matrixone.apps.domain.DomainConstants;
import com.matrixone.apps.domain.DomainObject;
import com.matrixone.apps.domain.DomainRelationship;
import com.matrixone.apps.domain.util.ContextUtil;
import com.matrixone.apps.domain.util.FrameworkException;
import com.matrixone.apps.domain.util.MapList;
import matrix.db.BusinessObject;
import matrix.db.Context;
import matrix.db.FileList;
import matrix.util.MatrixException;
import matrix.util.StringList;

import java.io.*;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * @Auther: Jack.Hao
 * @Date: 2021/4/13 15:30
 * @Description:
 */
public class EnoviaFileUtil
{


    private static String rel_TaskDeliverable = "Task Deliverable";


    /**
     * 获取任务的交付物
     *
     * @param context
     * @param taskId
     * @return
     */
    public static MapList getTaskDeliverableFiles(Context context, String taskId) throws Exception
    {
        Task task = new Task(DomainObject.newInstance(context, taskId));
        return getTaskDeliverableFiles(context, task);
    }

    /**
     * 获取任务的 参考文档
     *
     * @param context
     * @param taskId
     * @return
     */
    public static MapList getTaskReferenceDocument(Context context, String taskId) throws Exception
    {
        Task task = new Task(DomainObject.newInstance(context, taskId));
        return getTaskReferenceDocument(context, task);
    }


    /**
     * 获取任务关联的交付物
     *
     * @param context
     * @param task
     * @return
     */
    public static MapList getTaskDeliverableFiles(Context context, Task task) throws Exception
    {
        StringList busList = new StringList();
        StringList relList = new StringList();
        busList.add(DomainConstants.SELECT_ID);
        busList.add(DomainConstants.SELECT_TYPE);
        busList.add(DomainConstants.SELECT_NAME);
        busList.add(DomainConstants.SELECT_REVISION);
        relList.add(DomainConstants.SELECT_RELATIONSHIP_ID);
        return getTaskDeliverableFiles(context, task, busList, relList);
    }

    /**
     * 获取任务关联的交付物
     *
     * @param context
     * @param task
     * @return
     */
    public static MapList getTaskDeliverableFiles(Context context, Task task, StringList busList, StringList relList) throws Exception
    {
        return HDomainObject.getRelatedObjectsAttr(context, task, "*", Constants.rel_TaskDeliverable, busList, relList, false, true, (short) 1);
    }


    /**
     * 获取任务参考文档
     *
     * @param context
     * @param task
     * @return
     */
    public static MapList getTaskReferenceDocument(Context context, Task task) throws Exception
    {
        StringList busList = new StringList();
        StringList relList = new StringList();
        busList.add(DomainConstants.SELECT_ID);
        busList.add(DomainConstants.SELECT_TYPE);
        busList.add(DomainConstants.SELECT_NAME);
        busList.add(DomainConstants.SELECT_REVISION);
        relList.add(DomainConstants.SELECT_RELATIONSHIP_ID);
        return getTaskReferenceDocument(context, task, busList, relList);
    }

    /**
     * 获取任务参考文档
     *
     * @param context
     * @param task
     * @return
     */
    public static MapList getTaskReferenceDocument(Context context, Task task, StringList busList, StringList relList) throws Exception
    {
        return HDomainObject.getRelatedObjectsAttr(context, task, "*", Constants.rel_ReferenceDocument, busList, relList, false, true, (short) 1);
    }


    /**
     * 获取任务参考文档
     *
     * @param context
     * @param objectId
     * @return
     * @throws FrameworkException
     */
    public static MapList getObjectReferenceDocument(Context context, String objectId) throws Exception
    {
        return getObjectReferenceDocument(context, DomainObject.newInstance(context, objectId));
    }


    /**
     * 获取任务参考文档
     *
     * @param context
     * @param domainObject
     * @return
     * @throws FrameworkException
     */
    public static MapList getObjectReferenceDocument(Context context, DomainObject domainObject) throws Exception
    {
        StringList busList = new StringList();
        StringList relList = new StringList();
        busList.add(DomainConstants.SELECT_ID);
        busList.add(DomainConstants.SELECT_TYPE);
        busList.add(DomainConstants.SELECT_NAME);
        busList.add(DomainConstants.SELECT_REVISION);
        relList.add(DomainConstants.SELECT_RELATIONSHIP_ID);
        return getObjectReferenceDocument(context, domainObject, busList, relList);
    }


    /**
     * 获取任务参考文档
     *
     * @param context
     * @param domainObject
     * @return
     * @throws FrameworkException
     */
    public static MapList getObjectReferenceDocument(Context context, DomainObject domainObject, StringList busList, StringList relList) throws Exception
    {
        return HDomainObject.getRelatedObjectsAttr(context, domainObject, "*", Constants.rel_ReferenceDocument, busList, relList, false, true, (short) 1);
    }


    /**
     * 下载参考文档到指定路径
     *
     * @param context
     * @param domainObject
     * @param dirPath
     * @return
     * @throws MatrixException
     */
    public static boolean documentCheckOutFiles(Context context, DomainObject domainObject, String dirPath) throws MatrixException
    {

        if (!domainObject.exists(context))
        {
            return false;
        }
        if (!dirPath.endsWith(File.separator))
        {
            dirPath = dirPath + File.separator;
        }
        File dir = new File(dirPath);
        if (!dir.exists())
        {
            dir.mkdirs();
        }
        MapList allFiles = domainObject.getAllFiles(context);
        for (int i = 0; i < allFiles.size(); i++)
        {
            Map map_i = (Map) allFiles.get(i);
            String format = (String) map_i.get("format");
            map_i.remove("format");
            FileList files_i = new FileList();
            Set keySet = map_i.keySet();
            Iterator iterator = keySet.iterator();
            while (iterator.hasNext())
            {
                String key_i = (String) iterator.next();
                String value_i = (String) map_i.get(key_i);
                matrix.db.File file_i = new matrix.db.File(value_i, format);
                files_i.add(file_i);
            }
            domainObject.checkoutFiles(context, false, format, files_i, dirPath);
        }
        return true;
    }


    /**
     * @param context
     * @param domainObject
     * @param dirPath
     * @return
     * @throws MatrixException
     */
    public static boolean modelCheckInFiles(Context context, DomainObject domainObject, String dirPath) throws MatrixException
    {
        if (!domainObject.exists(context))
        {
            return false;
        }
        if (!dirPath.endsWith(File.separator))
        {
            dirPath = dirPath + File.separator;
        }
        File dir = new File(dirPath);
        File[] files = dir.listFiles();
        String type = domainObject.getType(context);

        try
        {
            for (File file : files)
            {
                String fileName = file.getName();
                String format = "";
                if (fileName.endsWith("xlsx"))
                {
                    format = "list";
                } else if (fileName.endsWith("3dxml"))
                {
                    format = "model";
                } else
                {
                    continue;
                }
                Document doc = new Document();
                String activeAndLatestVersion = doc.getUniqueName(context);
                activeAndLatestVersion = doc.getUniqueName("", 14);
                DomainObject activeObj = DomainObject.newInstance(context);
                activeObj.createObject(context, type, activeAndLatestVersion, "1", "Version", "eService Production");
                String activeAndLatestId = activeObj.getInfo(context, DomainObject.SELECT_ID);
                ContextUtil.pushContext(context);
                domainObject.checkinFile(context, true, true, DomainConstants.EMPTY_STRING, format, fileName, dirPath);
                activeObj.setAttributeValue(context, "Title", file.getName());
                activeObj.setAttributeValue(context, "Is Version Object", "True");
                DomainObject strObjectActiveLatest = DomainObject.newInstance(context, activeAndLatestId);
                DomainRelationship.connect(context, domainObject, "Active Version", strObjectActiveLatest);
                DomainRelationship.connect(context, domainObject, "Latest Version", strObjectActiveLatest);
                ContextUtil.popContext(context);
            }
        } catch (MatrixException e)
        {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * @param context
     * @param businessObject
     * @param dirPath
     * @return
     * @throws MatrixException
     */
    public static boolean businessObjectCheckInFile(Context context, BusinessObject businessObject, String dirPath, String format) throws MatrixException
    {
        if (!businessObject.exists(context))
        {
            return false;
        }
        //System.out.println("dirPath = " + dirPath);
        if (!dirPath.endsWith(File.separator))
        {
            dirPath = dirPath + File.separator;
        }
        File dir = new File(dirPath);
        File[] files = dir.listFiles();
        if (files == null || files.length == 0)
        {
            return true;
        }
        ContextUtil.pushContext(context);
        for (File file : files)
        {
            String fileName = file.getName();
            businessObject.checkinFile(context, true, true, DomainConstants.EMPTY_STRING, format, fileName, dirPath);
        }
        ContextUtil.popContext(context);
        return true;
    }


    /**
     * @param str
     * @return
     */
    public static boolean isNumeric(String str)
    {
        for (int i = str.length(); --i >= 0; )
        {
            if (!Character.isDigit(str.charAt(i)))
            {
                return false;
            }
        }
        return true;
    }


    /**
     * @param context
     * @param domainObject
     * @param dirPath
     * @return
     * @throws MatrixException
     */
    public static boolean documentCheckInFiles(Context context, DomainObject domainObject, String dirPath, String format) throws MatrixException
    {

        if (!domainObject.exists(context))
        {
            return false;
        }
        //System.out.println("dirPath = " + dirPath);
        if (!dirPath.endsWith(File.separator))
        {
            dirPath = dirPath + File.separator;
        }
        File dir = new File(dirPath);
        File[] files = dir.listFiles();
        String type = domainObject.getType(context);
        try
        {
            for (File file : files)
            {
                Document doc = new Document();
                String activeAndLatestVersion = doc.getUniqueName(context);
                activeAndLatestVersion = doc.getUniqueName("", 14);
                DomainObject activeObj = DomainObject.newInstance(context);
                activeObj.createObject(context, type, activeAndLatestVersion, "1", "Version", "eService Production");
                String activeAndLatestId = activeObj.getInfo(context, DomainObject.SELECT_ID);
                String fileName = file.getName();
                ContextUtil.pushContext(context);
                domainObject.checkinFile(context, true, true, DomainConstants.EMPTY_STRING, format, fileName, dirPath);
                activeObj.setAttributeValue(context, "Title", file.getName());
                activeObj.setAttributeValue(context, "Is Version Object", "True");
                DomainObject strObjectActiveLatest = DomainObject.newInstance(context, activeAndLatestId);
                DomainRelationship.connect(context, domainObject, "Active Version", strObjectActiveLatest);
                DomainRelationship.connect(context, domainObject, "Latest Version", strObjectActiveLatest);
                ContextUtil.popContext(context);
            }
        } catch (MatrixException e)
        {
            e.printStackTrace();
            return false;
        }

        return true;
    }


    /**
     * @param context
     * @param objectId
     * @param outDirPath
     * @return
     * @throws MatrixException
     */
    public static boolean documentCheckOutFiles(Context context, String objectId, String outDirPath) throws MatrixException
    {
        DomainObject domainObject = DomainObject.newInstance(context, objectId);
        return documentCheckOutFiles(context, domainObject, outDirPath);
    }


    /**
     * @param context
     * @param domainObject
     * @param file
     * @return
     * @throws MatrixException
     */
    public static boolean documentCheckInFile(Context context, DomainObject domainObject, File file, String format) throws MatrixException
    {

        if (!domainObject.exists(context))
        {
            return false;
        }

        if (!file.exists() || !file.isFile())
        {
            return true;
        }
        String dirPath = file.getParent();
        String type = domainObject.getType(context);
        try
        {

            Document doc = new Document();
            String activeAndLatestVersion = doc.getUniqueName(context);
            activeAndLatestVersion = doc.getUniqueName("", 14);
            DomainObject activeObj = DomainObject.newInstance(context);
            activeObj.createObject(context, type, activeAndLatestVersion, "1", "Version", "eService Production");
            String activeAndLatestId = activeObj.getInfo(context, DomainObject.SELECT_ID);
            String fileName = file.getName();
            ContextUtil.pushContext(context);
            domainObject.checkinFile(context, true, true, DomainConstants.EMPTY_STRING, format, fileName, dirPath);
            activeObj.setAttributeValue(context, "Title", file.getName());
            activeObj.setAttributeValue(context, "Is Version Object", "True");
            DomainObject strObjectActiveLatest = DomainObject.newInstance(context, activeAndLatestId);
            DomainRelationship.connect(context, domainObject, "Active Version", strObjectActiveLatest);
            DomainRelationship.connect(context, domainObject, "Latest Version", strObjectActiveLatest);
            ContextUtil.popContext(context);

        } catch (MatrixException e)
        {
            e.printStackTrace();
            return false;
        }

        return true;
    }


    /**
     * 下载所有的文件到本地
     *
     * @param context      上下文
     * @param domainObject 对象
     * @param dirPath      输出根目录
     * @return
     * @throws MatrixException
     */
    public static boolean checkOutAllFilesToLocal(Context context, DomainObject domainObject, String dirPath) throws Exception
    {
//        byte[] buffer = new byte[10240];
        if (!domainObject.exists(context))
        {
            return false;
        } else
        {
            if (!dirPath.endsWith(File.separator))
            {
                dirPath = dirPath + File.separator;
            }

            File dir = new File(dirPath);
            if (!dir.exists())
            {
                dir.mkdirs();
            }

            MapList allFiles = domainObject.getAllFiles(context);

            for (int i = 0; i < allFiles.size(); ++i)
            {
                Map map_i = (Map) allFiles.get(i);
                String format = (String) map_i.get("format");
                map_i.remove("format");
                Set keySet = map_i.keySet();
                Iterator iterator = keySet.iterator();
                while (iterator.hasNext())
                {
                    String key_i = (String) iterator.next();
                    String value_i = (String) map_i.get(key_i);
//                    matrix.db.File file_i = new matrix.db.File(value_i, format);
//                    OutputStream out = new FileOutputStream(dirPath+File.separator+value_i);
//                    domainObject.checkoutFile(context, true, format, value_i, out);
//                    BufferedOutputStream bos = new BufferedOutputStream(out);
//                    bos.flush();
//                    bos.close();
                    OutputStream out = new FileOutputStream(dirPath + File.separator + value_i);
                    domainObject.checkoutFile(context, true, format, value_i, out);
                    out.flush();
                    out.close();
                }
            }
            return true;
        }
    }


    /**
     * 下载所有的文件到本地
     *
     * @param context      上下文
     * @param domainObject 对象
     * @param dirPath      输出根目录
     * @return
     * @throws MatrixException
     */
    public static StringList checkOutAllFilesToLocalWidthResult(Context context, DomainObject domainObject, String dirPath) throws Exception
    {
        StringList result = new StringList();
//        byte[] buffer = new byte[10240];
        if (!domainObject.exists(context))
        {
            return result;
        } else
        {
            if (!dirPath.endsWith(File.separator))
            {
                dirPath = dirPath + File.separator;
            }

            File dir = new File(dirPath);
            if (!dir.exists())
            {
                dir.mkdirs();
            }

            MapList allFiles = domainObject.getAllFiles(context);

            for (int i = 0; i < allFiles.size(); ++i)
            {
                Map map_i = (Map) allFiles.get(i);
                String format = (String) map_i.get("format");
                map_i.remove("format");
                Set keySet = map_i.keySet();
                Iterator iterator = keySet.iterator();
                while (iterator.hasNext())
                {
                    String key_i = (String) iterator.next();
                    String fileName_i = (String) map_i.get(key_i);
//                    matrix.db.File file_i = new matrix.db.File(fileName_i, format);
//                    OutputStream out = new FileOutputStream(dirPath+File.separator+value_i);
//                    domainObject.checkoutFile(context, true, format, value_i, out);
//                    BufferedOutputStream bos = new BufferedOutputStream(out);
//                    bos.flush();
//                    bos.close();
//                    String outPath_i = dirPath + File.separator + fileName_i;
                    String outPath_i = dirPath + fileName_i;
                    OutputStream out = new FileOutputStream(outPath_i);
                    domainObject.checkoutFile(context, true, format, fileName_i, out);
                    out.flush();
                    out.close();

                    result.add(outPath_i);
                }
            }
            return result;
        }
    }


    /**
     * 下载指定 format 文件名  文件到本地
     *
     * @param context      上下文
     * @param domainObject 对象
     * @param dirPath      保存目录
     * @param format       格式
     * @param fileName     文件名称
     * @return
     * @throws Exception
     */
    public static boolean checkOutFileToLocal(Context context, DomainObject domainObject, String dirPath, String format, String fileName) throws Exception
    {
//        byte[] buffer = new byte[10240];
        if (!domainObject.exists(context))
        {
            return false;
        } else
        {
            if (!dirPath.endsWith(File.separator))
            {
                dirPath = dirPath + File.separator;
            }

            File dir = new File(dirPath);
            if (!dir.exists())
            {
                dir.mkdirs();
            }

            OutputStream out = new FileOutputStream(dirPath + File.separator + fileName);
            domainObject.checkoutFile(context, true, format, fileName, out);
            out.flush();
            out.close();

//            OutputStream out = new FileOutputStream(dirPath + File.separator + value_i);
//            domainObject.checkoutFile(context, true, format, value_i, out);
//            BufferedOutputStream bos = new BufferedOutputStream(out);
//            bos.flush();
//            bos.close();
            return true;
        }
    }

}
